package com.cloud.pole.cmpay.service.impl;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.annotation.Resource;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.cloud.pole.cmpay.constant.CmPayConfig;
import com.cloud.pole.cmpay.constant.CmPayConstant;
import com.cloud.pole.cmpay.model.CommonMsg;
import com.cloud.pole.cmpay.model.GetTokenReqMsg;
import com.cloud.pole.cmpay.service.CmPayService;
import com.cloud.pole.cmpay.util.AesUtil;
import com.cloud.pole.cmpay.util.Base64Utils;
import com.cloud.pole.cmpay.util.DigestUtils;
import com.cloud.pole.cmpay.util.RSAUtils;
import com.cloud.pole.common.util.DateUtils;
import com.cloud.pole.common.util.HttpClientUtils;
import com.cloud.pole.common.util.OrderNoUtils;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class CmPayServiceImpl implements CmPayService {
	
	@Resource
	private CmPayConfig payConfig;
	
	public SortedMap<String, Object> initCommMap(CommonMsg msg) {
		// 过滤空 设置 TreeMap
		SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
		// 加入
		packageParams.put("journalNo", msg.getJournalNo());
		packageParams.put("requestTime", msg.getRequestTime());
		packageParams.put("clientId", msg.getClientId());
		packageParams.put("subClientId", msg.getSubClientId());
		packageParams.put("version", msg.getVersion());
		packageParams.put("signType", msg.getSignType());
		packageParams.put("appVersion", msg.getAppVersion());
		packageParams.put("osVersion", msg.getOsVersion());
		packageParams.put("terminalType", msg.getTerminalType());
		packageParams.put("terminalId", msg.getTerminalId());
		packageParams.put("deviceId", msg.getDeviceId());
		return packageParams;
	}
	
	public String getRsaSign(SortedMap<String, Object> packageParams) {
		StringBuffer sb = new StringBuffer();
		Set es = packageParams.entrySet();
		Iterator it = es.iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			String k = (String)entry.getKey();
			String v = (String)entry.getValue();
			if(!StringUtils.isEmpty(k) && !StringUtils.isEmpty(v)){
				sb.append(k + v);
			}
		}
		log.debug("MD5加密前：{}", sb.toString());
		// MD5加密报文：
		String strMD5 = DigestUtils.md5DigestAsHex(sb.toString().getBytes());
		log.debug("MD5加密后：{}", strMD5);
		//RSA签名
		
		String strSign = Base64Utils.encode(RSAUtils.sign(payConfig.getPrivateKey(), strMD5));		
		return strSign;
	}
	

	  /**
     * post json
     * @param url
     * @param paramJson
     * @return
     */
    public String doPostJson(String url, String paramJson, String sign) {
        String out = null;
        HttpClient httpClient = new HttpClient();
        // 设置httpClient连接主机服务器超时时间：15000毫秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);
        // 创建post请求方法实例对象
        PostMethod postMethod = new PostMethod(url);
        // 设置post请求超时时间
        postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
        postMethod.addRequestHeader("Content-Type", "application/json;charset=UTF-8");
        
        postMethod.addRequestHeader("x-lemon-secure", payConfig.getLemonSecure());
        postMethod.addRequestHeader("x-lemon-sign", sign);
        String result = "";
        try {
            //json格式的参数解析
            //RequestEntity entity = new StringRequestEntity(paramJson, "application/json", "UTF-8");
        	RequestEntity entity = new StringRequestEntity(paramJson);
            postMethod.setRequestEntity(entity);

            httpClient.executeMethod(postMethod);
            result = postMethod.getResponseBodyAsString();
    		log.info("转码前result ：{}", result);
    		log.info("转码后result ：{}",  new String(result.getBytes("ISO8859-1"), "UTF-8"));

            return result;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            postMethod.releaseConnection();
        }
        return result;
    }

	
	
	@Override
	public Map<String, Object> getToken(String mobileNo) throws Exception {
		//RSA签名数据
		CommonMsg reqMsg = new CommonMsg();
		//排序后，待签名报文：
		SortedMap<String, Object> sortMap = initCommMap(reqMsg);
		sortMap.put("mobileNo", mobileNo);
		String strSign = getRsaSign(sortMap);
		String paramJson = JSON.toJSONString(sortMap);
		log.info("请求签名:{}", strSign);
		log.info("请求json:{}", paramJson);
		
		String reqUrl = CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.TOKEN_RUL;
		String strResp = doPostJson(reqUrl, paramJson, strSign);
		log.info("请求地址:{}", reqUrl);
		log.info("响应报文:{}", strResp);
		
		Map<String, Object> map = new HashMap<>();
		map.put("strResp", strResp);
		//解析
		return map;
	}

	@Override
	public Map<String, Object> getGoodsGrantResult(Map<String, Object> params) throws Exception {
		// TODO Auto-generated method stub
		//RSA签名数据
		CommonMsg reqMsg = new CommonMsg();
		//排序后，待签名报文：
		SortedMap<String, Object> sortMap = initCommMap(reqMsg);
		sortMap.putAll(params);

		String strSign = getRsaSign(sortMap);
		String paramJson = JSON.toJSONString(sortMap);
		log.info("请求签名:{}", strSign);
		log.info("请求json:{}", paramJson);
		
		String reqUrl = CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.GOODS_GRANT_RESULT_URL;
		String strResp = doPostJson(reqUrl, paramJson, strSign);
		
		log.info("请求地址:{}", CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.GOODS_GRANT_RESULT_URL);
		log.info("响应报文:{}", strResp);
		
		return null;
	}

	@Override
	public Map<String, Object> getPayment(Map<String, Object> params) throws Exception {
		//RSA签名数据
		CommonMsg reqMsg = new CommonMsg();
		//排序后，待签名报文：
		SortedMap<String, Object> sortMap = initCommMap(reqMsg);
		sortMap.putAll(params);
		
		String strSign = getRsaSign(sortMap);
		String paramJson = JSON.toJSONString(sortMap);
		log.info("请求签名:{}", strSign);
		log.info("请求json:{}", paramJson);
		String reqUrl = CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.PAYMENT_URL;
		String strResp = doPostJson(reqUrl, paramJson, strSign);
		
		log.info("请求地址:{}", reqUrl);
		log.info("响应报文:{}", strResp);
		
		return null;
	}

	@Override
	public Map<String, Object> geReturnQuery(Map<String, Object> params) throws Exception {
		//RSA签名数据
		CommonMsg reqMsg = new CommonMsg();
		//排序后，待签名报文：
		SortedMap<String, Object> sortMap = initCommMap(reqMsg);
		sortMap.putAll(params);
		
		String strSign = getRsaSign(sortMap);
		String paramJson = JSON.toJSONString(sortMap);
		log.info("请求签名:{}", strSign);
		log.info("请求json:{}", paramJson);
		String reqUrl = CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.RETURNS_QUERY_URL;
		String strResp = doPostJson(reqUrl, paramJson, strSign);
		
		log.info("请求地址:{}", reqUrl);
		log.info("响应报文:{}", strResp);
		
		return null;
	}


	@Override
	public Map<String, Object> returnRecharge(Map<String, Object> params) throws Exception {
		//RSA签名数据
		CommonMsg reqMsg = new CommonMsg();
		//排序后，待签名报文：
		SortedMap<String, Object> sortMap = initCommMap(reqMsg);
		sortMap.putAll(params);
		
		String strSign = getRsaSign(sortMap);
		String paramJson = JSON.toJSONString(sortMap);
		log.info("请求签名:{}", strSign);
		log.info("请求json:{}", paramJson);
		String reqUrl = CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.RETURN_RECHARGE_URL;
		String strResp = doPostJson(reqUrl, paramJson, strSign);
		
		log.info("请求地址:{}", reqUrl);
		log.info("响应报文:{}", strResp);
		return null;
	}

	@Override
	public Map<String, Object> getOrdersStatusQuery(Map<String, Object> params) throws Exception {
		//RSA签名数据
		CommonMsg reqMsg = new CommonMsg();
		//排序后，待签名报文：
		SortedMap<String, Object> sortMap = initCommMap(reqMsg);
		sortMap.putAll(params);
		
		String strSign = getRsaSign(sortMap);
		String paramJson = JSON.toJSONString(sortMap);
		log.info("请求签名:{}", strSign);
		log.info("请求json:{}", paramJson);
		String reqUrl = CmPayConstant.CM_PAY_BASE_URL + CmPayConstant.ORDERS_STATUS_QUERY_URL;
		String strResp = doPostJson(reqUrl, paramJson, strSign);
		
		log.info("请求地址:{}", reqUrl);
		log.info("响应报文:{}", strResp);
		return null;
	}
	
	//3.1.1.商品签收数据文件（加密文件）
	@Override
	public Map<String, Object> testGoodsReceiveFile(Map<String, Object> params) throws Exception {
		// TODO Auto-generated method stub
		//写入文件
		String fileName = "merc_24298_01_"+ DateUtils.formatDate(new Date(), "yyyyMMdd") +"_001.DAT";
//		String path = "/data/cloud/file/";
		String path = payConfig.getRecvFilePath();
		
		File file = new File(path  + fileName);
        // 检测是否存在目录
        if (!file.getParentFile().exists()) {
        	file.getParentFile().mkdirs();
        }
		if(file.exists()) {
			file.deleteOnExit();
		}
		
    	String key = payConfig.getFileAesKey();
		String content = (String)params.get("content");
		
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        try {
			byte[] bt = AesUtil.encrypt("1|", key);
			String encryptResultStr = AesUtil.parseByte2HexStr(bt);
			bw.write(encryptResultStr + "\n");
//			bw.newLine();

			bt = AesUtil.encrypt(content, key);
			encryptResultStr = AesUtil.parseByte2HexStr(bt);
			bw.write(encryptResultStr + "\n");
//			bw.newLine();

			bt = AesUtil.encrypt("@END@", key);
			encryptResultStr = AesUtil.parseByte2HexStr(bt);
			bw.write(encryptResultStr + "\n");
//			bw.newLine();
        
                
            bw.flush();
            bw.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bw.close();
        }
		return null;
	}

    /**
     * Java文件操作 获取不带扩展名的文件名
     */
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot >-1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }
    
	//3.2.1.办理/退款对账文件（解密文件）
	@Override
	public Map<String, Object> testDealResultFile(MultipartFile file) throws Exception {
    	String key = payConfig.getFileAesKey();

		String strOriginalFilename = file.getOriginalFilename();
		String fileName = strOriginalFilename;
//		String path = "/data/cloud/file-recv/";
		String path = payConfig.getOutFilePath();
		
        // getCanonicalFile 可解析正确各种路径
        File dest = new File(path + fileName).getCanonicalFile();
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        // 文件写入
        file.transferTo(dest);
        
        //解密
        String line = null;
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(dest), "UTF-8"));
        while ((line = br.readLine()) != null) {
        	 String result = "";
        	 byte[] decryptFrom = AesUtil.parseHexStr2Byte(String.valueOf(result) + line);
             byte[] decryptResult = AesUtil.decrypt(decryptFrom, key);
             result = new String(decryptResult, "UTF-8");
             log.info("result is:" + result);
        }

		return null;
	}
}
